package cathttp

import (
	"bytes"
	"net/http"
	"net/url"
	"regexp"
	"strings"
)

///
// * 路由框架核心实现
// * 创建于: 2019-7-12
// * 修改于: 2019-7-13
// * 版本: 0.0.1
// ! ----------------
// * 代码流程
// ?    CatHTTP -> CatVerify -> CatHandle
// *       |-TG        |-T           |-T
// *   [HandlePath]----X             |
// *  [HandleRegExp]---X             |
// *       |           |             |
// *       |    ValidationHandle-----? -----X
// *       |-E         |-E           |      |-E
// *       |           |         ServeHTTP  |
// *       X-----------X--------------------X
// *                   |
// *            http.WriteHeader
// ?   CatVerify
// *       |-(ValidationRouting:true)
// * [ValidationHandle] -?- (ok:true) --- func(Value *CatValue) --------X
// *                     |- (ok:false)           |-(return:true)        | -(return:false)
// *                     J                       |                      |
// *                                         CatHandle           http.WriteHeader
// ! ----------------
// * 定义
// *  G: 调度 X: 链接 E: 错误 J: 跳过 T: 所在类(type)
// *  Set: 设置 Get: 得到 Call: 调用
// *  ?: 分支 [xxx]: 数组 (x:x): 附加关系
// *  -: 流程 |: 流程 |-X: 链接流程 |-E: 错误流程
///

// CatValue HTTP通用值类
type CatValue struct {
	w http.ResponseWriter
	r *http.Request
	// * 返回码状态
	header bool
}

// WriteHeader 写标题
func (Value *CatValue) WriteHeader(statusCode int) {
	if !Value.header {
		Value.header = true
		Value.w.WriteHeader(statusCode)
	}
}

// CatValueToCatConn 类型转换
func CatValueToCatConn(Value *CatValue, Conn *CatConn) (err error) {
	// * 得到内容
	buf := bytes.NewBuffer(Conn.Data)
	Conn.Size, err = buf.ReadFrom(Value.r.Body)
	Conn.Data = buf.Bytes()
	if err != nil {
		return
	}
	// * 处理内容
	Conn.Addr = Value.r.RemoteAddr
	(*Conn).Write = Value.w.Write
	return
}

// CatVerify 路由验证类
type CatVerify struct {
	ValidationRouting bool                       // * 验证路由
	ValidationHandle  func(Value *CatValue) bool // * 路由验证处理函数
}

// CatHandle 路由接口类
type CatHandle struct {
	Verify       *map[string]*CatVerify
	ServeHTTP    func(Value *CatValue) // * 处理过程
	ProtocolType string                // * 协议类型 GET/POST 协议
}

// CatHTTP HTTP核心类
type CatHTTP struct {
	Dispatcher Dispatcher // ? 调度器
	// * 路由
	HandlePath   map[string]CatHandle // * [路由]路径路由
	HandleRegExp map[string]CatHandle // * [正则]正则路由
}

// ServeHTTP 功能实现
func (HTTP *CatHTTP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// * 获得调度
	dispatch := HTTP.Dispatcher.Get()
	// * 发送到调度
	dispatch.Set(&CatValue{w, r, false})
	// * 等待调度结束
	<-dispatch.Lock
}

// Init 初始化
// * min int  最少协程数量
// * max int  最大协程数量
// * CallBack 无法创建携程回调
func (HTTP *CatHTTP) Init(min int, max int, CallBack func()) {
	// * 初始化变量
	HTTP.HandlePath = make(map[string]CatHandle)   // * 路径路由
	HTTP.HandleRegExp = make(map[string]CatHandle) // * 正则路由
	// * 初始化超时
	HTTP.Dispatcher.Init(min, max, true, true, func(value interface{}) interface{} {
		// ? 调度
		valueHTTP, ok := value.(*CatValue)
		if !ok {
			valueHTTP.WriteHeader(http.StatusNotFound)
			return nil
		}
		// * 解析
		defer valueHTTP.r.Body.Close()
		// * 处理访问路径
		valueURL, _ := url.PathUnescape(valueHTTP.r.URL.String())
		// * 去除后戳
		N := strings.Index(valueURL, "?")
		if N != -1 {
			valueURL = (valueURL)[:N]
		}
		// * 目标路由处理
		Dispose := func(handle CatHandle) {
			// * 协议类型
			if valueHTTP.r.Method != handle.ProtocolType {
				// ? 协议验证失败返回 400
				valueHTTP.WriteHeader(http.StatusBadRequest)
				return
			}
			// * 是否验证路由
			for _, Verify := range *handle.Verify {
				if Verify.ValidationRouting {
					if !Verify.ValidationHandle(valueHTTP) {
						// ? 权限验证失败 401
						valueHTTP.WriteHeader(http.StatusUnauthorized)
						return
					}
				}
			}
			// * 传递到处理
			handle.ServeHTTP(valueHTTP)
		}
		// ? 优先处理路径路由
		if handle, ok := HTTP.HandlePath[valueURL]; ok {
			Dispose(handle)
			return nil
		}
		// ? 处理正则路由
		for regExp, handle := range HTTP.HandleRegExp {
			if ok, _ := regexp.MatchString(regExp, valueURL); ok {
				Dispose(handle)
				return nil
			}
		}
		// ? 返回 404
		valueHTTP.WriteHeader(http.StatusNotFound)
		return nil
	}, CallBack)
}

// Listen 初始化
func (HTTP *CatHTTP) Listen(addr string) error {
	// 创建路由
	mux := http.NewServeMux()
	mux.Handle("/", HTTP)
	// 注册
	err := http.ListenAndServe(addr, mux)
	if err != nil {
		return err
	}
	return err
}

// NewRouting 创建路由管理
// * Path 根路径
func (HTTP *CatHTTP) NewRouting(Path string) *CatRouting {
	return &CatRouting{
		Verify: new(map[string]*CatVerify),
		http:   HTTP,
		path:   Path,
	}
}
